package com.ssm.platform.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssm.basis.model.util.BeanUtil;
import com.ssm.platform.mapper.GroupMembersMapper;
import com.ssm.platform.mapper.GroupMenusMapper;
import com.ssm.platform.mapper.GroupsMapper;
import com.ssm.platform.mapper.MenusMapper;
import com.ssm.platform.pojo.domain.GroupMembersDo;
import com.ssm.platform.pojo.domain.GroupMenusDo;
import com.ssm.platform.pojo.domain.GroupsDo;
import com.ssm.platform.pojo.domain.MenusDo;
import com.ssm.platform.pojo.vo.MenusVo;
import com.ssm.platform.service.IMenusService;
import lombok.RequiredArgsConstructor;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class MenusServiceImpl extends ServiceImpl<MenusMapper, MenusDo> implements IMenusService {
    final GroupMembersMapper groupMembersMapper;
    final GroupsMapper groupsMapper;
    final GroupMenusMapper groupMenusMapper;
    final MenusMapper menusMapper;
    static final Long ROOT_NODE_PARENT_ID = 0L;
    static final List<MenusVo> EMPTY_LIST = new ArrayList<>();

    @Override
    public List<MenusVo> list(String username) {
        Set<Long> groupIds = groupMembersMapper.selectList(Wrappers.<GroupMembersDo>lambdaQuery()
                .eq(GroupMembersDo::getUsername, username)
        ).stream().map(GroupMembersDo::getGroupId).collect(Collectors.toSet());
        groupIds = groupsMapper.listByIds(groupIds).stream().map(GroupsDo::getId).collect(Collectors.toSet());
        Set<Long> menusIds = groupMenusMapper.selectList(Wrappers.<GroupMenusDo>lambdaQuery()
                .in(GroupMenusDo::getGroupId, groupIds)
        ).stream().map(GroupMenusDo::getMenuId).collect(Collectors.toSet());

        return BeanUtil.copyListProperties(menusMapper.listByIds(menusIds), MenusVo::new);
    }

    @Override
    public List<MenusVo> tree(String username) {
        // List<MenusVo> menusVos = list(username);
        List<MenusVo> menusVos = ((IMenusService) AopContext.currentProxy()).list(username); // exposeProxy = true

        LinkedMultiValueMap<Long, MenusVo> parentIdMap = new LinkedMultiValueMap<>();
        menusVos.forEach(x -> parentIdMap.add(x.getParentId(), x));
        List<MenusVo> rootList = parentIdMap.get(ROOT_NODE_PARENT_ID);
        if (Objects.isNull(rootList)) {
            return EMPTY_LIST;
        }
        listToTree(rootList, parentIdMap);
        return rootList;
    }

    /**
     * @param rootList    根节点
     * @param parentIdMap 所有节点，按照 parentId 分组
     */
    List<MenusVo> listToTree(List<MenusVo> rootList, LinkedMultiValueMap<Long, MenusVo> parentIdMap) {
        for (MenusVo menusVo : rootList) {
            List<MenusVo> children = parentIdMap.get(menusVo.getId());
            if (Objects.isNull(children) || children.isEmpty()) {
                menusVo.setHasChild(false);
                menusVo.setChildren(EMPTY_LIST);
            } else {
                menusVo.setHasChild(true);
                menusVo.setChildren(listToTree(children, parentIdMap));
            }
        }
        return rootList;
    }
}
